package com.sw.rpc.bootstrap;

import com.sw.rpc.annotation.Service;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author sw
 * @project zdy-rpc
 * @description
 * @date 2020/5/17 22:10
 */
public class SpringApplication {
    /**
     * 存放bean
     */
    public static ConcurrentHashMap<String,Object> beanConaoners=new ConcurrentHashMap<>();
    /**
     * 获取到所有的类
     */
    private static Set<Class<?>> totalClass=new LinkedHashSet<>();
    public static void run(Class c,String [] args) throws IOException, InstantiationException, IllegalAccessException {
        //扫描注解类
        //PackageScan packageScan = (PackageScan) c.getAnnotation(PackageScan.class);
        //扫描的包
       //String[] packages = packageScan.value();
        //for(String p:packages) {
            doScan(c.getPackage().getName());
        //}
        parseAnnotationServiceClass();
        System.out.println("容器初始化完成："+beanConaoners);
    }
    /**
     * ioc 容器
     * @param scanPackage  扫描的
     */
    private static void doScan(String scanPackage) throws IOException {
        /**
         * 替换包名 转换路径
         */
        String packageDirName = scanPackage.replace('.', '/');
        /**
         * 得到文件全路径
         */
        Enumeration<URL> dirs=Thread.currentThread().getContextClassLoader().getResources(packageDirName);
        while (dirs.hasMoreElements()){
            URL url=dirs.nextElement();
            /**
             * 名称 尝试获取
             */
            String protocol=url.getProtocol();
            System.out.println(url.getProtocol());
            if("file".equals(protocol)){
                String filePath= URLDecoder.decode(url.getFile(),"utf-8");
                findClassFromPackage(scanPackage, filePath,true,totalClass);
            }
        }
    }

    /**
     * 找到所有的类
     * @param packageName
     * @param packagePath
     * @param isDe
     * @param classes
     */
    private static void findClassFromPackage(String packageName, String packagePath, Boolean isDe, Set<Class<?>> classes){
        // 获取此包的目录 建立一个File
        File dir = new File(packagePath);
        // 如果不存在或者 也不是目录就直接返回
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 如果存在 就获取包下的所有文件 包括目录
        File[] dirfiles = dir.listFiles(new FileFilter() {
            // 如果是文件，递归循环，拿到以.class结尾的文件
            public boolean accept(File file) {
                return (isDe && file.isDirectory()) || (file.getName().endsWith(".class"));
            }
        });
        // 循环所有文件
        for (File file : dirfiles) {
            // 如果是目录 则继续扫描
            if (file.isDirectory()) {
                findClassFromPackage(packageName + "." + file.getName(), file.getAbsolutePath(), isDe, classes);
            } else {
                // 如果是java类文件 去掉后面的.class 只留下类名
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    // 添加到集合中去
                    classes.add(Class.forName(packageName + '.' + className));
                } catch (ClassNotFoundException e) {
                    // log.error("添加用户自定义视图类错误 找不到此类的.class文件");
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 从解析的class中获取Service注解信息
     * @return
     */
    public static ConcurrentHashMap<String,Object> parseAnnotationServiceClass() throws IllegalAccessException, InstantiationException {
        for (Class<?> clazz : totalClass) {
            Service annotation = clazz.getAnnotation(Service.class);
            if (annotation != null) {
                System.out.println(clazz.getSimpleName());
                Object obj = clazz.newInstance();
                //key为接口类全限定类名称
                if (clazz.getInterfaces() != null && clazz.getInterfaces().length > 0) {
                    String facesName = clazz.getInterfaces()[0].getName();
                    beanConaoners.put(facesName, obj);
                }
                //key为类名首字母小写
                if (null==annotation.value() || "".equalsIgnoreCase(annotation.value())) {
                    String beanId = toLowerCaseFirstOne(clazz.getSimpleName());
                    beanConaoners.put(beanId, obj);
                } else {
                    beanConaoners.put(annotation.value(), obj);
                }
                continue;
            }
        }
        return beanConaoners;
    }
    /**
     * 驼峰命名
     * @param s
     * @return
     */
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    public static Object getClass(String classId){
        return beanConaoners.get(classId);
    }

}
